﻿using System;
using System.Collections.Generic;

namespace SKBSecond
{

    class Program
    {
        static void Main()
        {
            /*
             Через "=>" будем указывать то, что должен вернуть метод.
             
             Проверим случай из задания, результат должен соответствовать примерам.
             CloseGeneric(typeof(IEnumerable<>), typeof(List<int>)) => typeof(IEnumerable<int>).
             CloseGeneric(typeof(IDictionary<,>), typeof(string)) => null
             
             В случаи, если первый аргумент не является generic-типом, должен вернуться null.
             CloseGeneric(typeof(int),typeof(int)) => null
             
             Можно попытаться предположить, как работает CloseGeneric. 
             Возможно, выясняется, является ли concreteType наследником openGeneric, и если является,
             то возвращается openGeneric с такими же параметрами шаблона как у concreteType.
             
             Если это так, то данный метод не будет работать для следующего теста, так как int не наследник Nullable, 
             хотя Nullable<int> удовлетворят первому и второму условиям задания.             
             CloseGeneric(typeof(Nullable<>),typeof(int)) => Nullable<int>
             
             Возможно, в реализации не проверяется является ли openGeneric generic-типом, а проверяется только возможность присваивания, 
             тогда IComparable подходит под первое условие.
             CloseGeneric(typeof(IComparable),typeof(int)) => null
             
             Несколько параметров у шаблона:
             CloseGeneric(typeof(IDictionary<,>),typeof(SortedDictionary<int,int>)) => IDictionary<int,int>
             
             Проверка внутренних классов:
             CloseGeneric(typeof(ICollectio<>),typeof(SortedDictionary<string,int>.ValueCollection)) => ICollection<int>
             
             Пусть у нас определены такие типы:
             class Type1 {}
             class Type2 : Type1 {}
             class Class1<T> where T : Type1 {}
             class Class2<T> : Class1<T> where T : Type2 {}
             Тогда так как Type2 это наследник Type1 то существует такой тип.
             CloseGeneric(typeof(Class1<>),typeof(Class2<Type2>)) => Class1<Type2>
            
            Общие размышления о работе метода:
            
            Рассмотрим подмножество случаев, когда openGeneric и concreteType являются generic-типами.
            Все generic-типы можно представить как упорядоченную алгебраическую структуру, с определённой на ней операцие сравнения IsAssignableFrom.
            
            Тогда метод CloseGeneric(A,B) будет возвращать тип A, если A < B , или null в другом случае.
            
            Проверим тестами некоторые свойства этой структуры.
            
            Представим, что у нас есть три типа A<T>,B<T>,C<T> которые связаны наследованием A<T> <- B<T> <- C<T>, возможно через какие то другие типы.
            Тогда для любых таких типов должно выполняться условие:
            CloseGeneric(typeof(A<>), CloseGeneric(typeof(B<>),typeof(C<int>))) == CloseGeneric(typeof(A<>),typeof(C<int>))
            
            Для любых типов A<T>,B<T> которые связаны наследованием A<T> <- B<T> должно также выполняться:
            CloseGeneric(typeof(A<>), CloseGeneric(typeof(A<>), typeof(B<int>))) == CloseGeneric(typeof(A<>), typeof(B<int>))
            */

            //Console.WriteLine(typeof(Class1<Type2>).IsAssignableFrom(typeof(Class2<Type2>)));
            //Console.WriteLine(typeof(ICollection<>).IsAssignableFrom(typeof(SortedDictionary<int,int>.ValueCollection)));
            //Console.WriteLine(typeof(ICollection<int>));
            //var x = new MyIntImpl<int>();
            //Console.WriteLine (typeof (IMyInterface<int>).IsAssignableFrom (x.GetType().Attributes));
            //Console.WriteLine(typeof(IMyInterface<int>).IsAssignableFrom(typeof(MyIntImpl<int>)));
        }
    }
}
